/**
*	@author Dr.Nguyen Hua Phung
*	@version 1.0
*	28/6/2006
* 	This class provides facilities for method generation
*
*/
package MP.codegeneration;

import MP.CompilationException;

abstract public class MachineCode {
	
}
class JasminCode extends MachineCode{
	
	private final static String END="\n";
	private static String INDENT = "\t";
	
	public String emitICONST(int i) throws CompilationException  {		
		if (i == -1){
			return INDENT + "iconst_m1" +END;			
		} else if (i >= 0 && i <= 5){
			return INDENT+"iconst_" + i +END;			
		} else 
		throw new IllegalOperandException();
	}
	
	public String emitBIPUSH(int i) throws CompilationException  {
		if ((i >= -128 && i < -1) || (i >5 && i <= 127))
			return INDENT + "bipush "+i +END;
		else
			throw new IllegalOperandException();
	}
	
	public String emitSIPUSH(int i) throws CompilationException  {
		if ((i >= -32768 && i < -128) || (i > 127 && i <= 32767))
			return INDENT +"sipush "+i +END;
		else
			throw new IllegalOperandException();
	}
	
	public String emitLDC(String in) throws CompilationException {	
		return INDENT +"ldc "+in +END;
	}
	
	public String emitFCONST(String in) throws CompilationException {
		if (in.equals("0.0")) {
			return INDENT +"fconst_0"  +END;
		} else if (in.equals("1.0")) {
			return INDENT +"fconst_1"  +END;
		} else if (in.equals("2.0")) {
			return INDENT +"fconst_2"  +END;
		} else
			throw new IllegalOperandException();
	}
	
	public String emitILOAD(int in) throws CompilationException {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT + "iload_"+in + END;
		else
			result = INDENT + "iload "+in + END;
		return result;
		
	}
	
	public String emitFLOAD(int in) throws CompilationException {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT +"fload_"+in + END;
		else
			result = INDENT +"fload "+in + END;

		return result;
	}	
	
	public String emitISTORE(int in) throws CompilationException {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT +"istore_"+in + END;
		else
			result = INDENT +"istore "+in + END;

		return result;
	}
	
	public String emitFSTORE(int in) throws CompilationException  {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT +"fstore_"+in + END;
		else
			result = INDENT +"fstore "+in + END;
		
		return result;
	}

	public String emitALOAD(int in) throws CompilationException {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT +"aload_"+in + END;
		else
			result = INDENT +"aload "+in + END;
		
		return result;
	}	

	public String emitASTORE(int in) throws CompilationException {
		String result;
		if (in >= 0 && in <= 3)
			result = INDENT +"astore_"+in + END;
		else
			result = INDENT +"astore "+in + END;
		
		return result;
	}	

	public String emitIASTORE() throws CompilationException {
		return INDENT+"iastore"+END;
	}
	public String emitFASTORE() throws CompilationException {
		return INDENT+"fastore"+END;
	}
	public String emitBASTORE() throws CompilationException {
		return INDENT+"bastore"+END;
	}
	public String emitIALOAD() throws CompilationException {
		return INDENT+"iaload"+END;
	}
	public String emitFALOAD() throws CompilationException {
		return INDENT+"faload"+END;
	}
	public String emitBALOAD() throws CompilationException {
		return INDENT+"baload"+END;
	}	
	public String emitGETSTATIC(String lexeme, String type) throws CompilationException {

		return INDENT+ "getstatic "+lexeme+" "+type+END;
	}
	
	public String emitPUTSTATIC(String lexeme, String type) throws CompilationException {

		return INDENT + "putstatic "+lexeme+" "+type+END;
	}	
	
	public String emitIADD()  throws CompilationException {
		return INDENT+"iadd"+END;
	}
	public String emitFADD()  throws CompilationException {
		return INDENT+"fadd"+END;
	}
	public String emitISUB()  throws CompilationException {
		return INDENT+"isub"+END;
	}
	public String emitFSUB()  throws CompilationException {
		return INDENT+"fsub"+END;
	}
	public String emitIMUL()  throws CompilationException {
		return INDENT+"imul"+END;
	}
	public String emitFMUL()  throws CompilationException {
		return INDENT+"fmul"+END;
	}
	public String emitIDIV()  throws CompilationException {
		return INDENT+"idiv"+END;
	}
	public String emitFDIV()  throws CompilationException {
		return INDENT+"fdiv"+END;
	}
	public String emitIAND()  throws CompilationException {
		return INDENT+"iand"+END;
	}
	public String emitIOR()  throws CompilationException {
		return INDENT+"ior"+END;
	}
	public String emitIFICMPEQ(int label)  throws CompilationException {
		return INDENT+"if_icmpeq Label"+label+END;
	}
	public String emitIFICMPNE(int label)  throws CompilationException {
		return INDENT+"if_icmpne Label"+label+END;
	}
	public String emitIFICMPLT(int label)  throws CompilationException {
		return INDENT+"if_icmplt Label"+label+END;
	}
	public String emitIFICMPLE(int label)  throws CompilationException {
		return INDENT+"if_icmple Label"+label+END;
	}
	public String emitIFICMPGT(int label)  throws CompilationException {
		return INDENT+"if_icmpgt Label"+label+END;
	}
	public String emitIFICMPGE(int label)  throws CompilationException {
		return INDENT+"if_icmpge Label"+label+END;
	}
	public String emitIFEQ(int label)  throws CompilationException {
		return INDENT+"ifeq Label"+label+END;
	}
	public String emitIFNE(int label)  throws CompilationException {
		return INDENT+"ifne Label"+label+END;
	}
	public String emitIFLT(int label)  throws CompilationException {
		return INDENT+"iflt Label"+label+END;
	}
	public String emitIFLE(int label)  throws CompilationException {
		return INDENT+"ifle Label"+label+END;
	}
	public String emitIFGT(int label)  throws CompilationException {
		return INDENT+"ifgt Label"+label+END;
	}
	public String emitIFGE(int label)  throws CompilationException {
		return INDENT+"ifge Label"+label+END;
	}
	
	public String emitLABEL(int label) throws CompilationException {
		return "Label"+label+":"+END;
	}
	
	public String emitGOTO(int label)  throws CompilationException {
		return INDENT+ "goto Label"+label+END;
	}
	public String emitINEG()throws CompilationException {
		return INDENT+ "ineg"+END;
	}
	public String emitFNEG()throws CompilationException {
		return INDENT+ "fneg"+END;
	}
	public String emitDUP() throws CompilationException {
		return INDENT+"dup"+END;
	}

	public String emitDUPX2() throws CompilationException {
		return INDENT+"dup_x2"+END;
	}	
	public String emitPOP() throws CompilationException {
		return INDENT+"pop"+END;
	}
	
	public String emitI2F() throws CompilationException {
		return INDENT+"i2f"+END;
	}
	
	public String emitNEWARRAY(String lexeme) throws CompilationException {
		return INDENT+"newarray "+lexeme+END;
	}
	public String emitINVOKESTATIC(String lexeme,String type) throws CompilationException {		
		return INDENT+"invokestatic "+lexeme+type+END;
	}
	public String emitINVOKESPECIAL() {
		return INDENT+"invokespecial java/lang/Object/<init>()V"+END;
	}
	public String emitINVOKEVIRTUAL(String lexeme,String type) throws CompilationException {
		return INDENT+"invokevirtual "+lexeme+type+END;
	}
	public String emitIRETURN()  throws CompilationException {
		return INDENT+"ireturn"+END;
	}
	public String emitFRETURN()  throws CompilationException {
		return INDENT+"freturn"+END;
	}
	public String emitRETURN()  throws CompilationException {
		return INDENT+"return"+END;
	}
	public String emitLIMITSTACK(int in) {
		return ".limit stack "+in+END;
	}
	public String emitFCMPL() {
		return INDENT+"fcmpl"+END;
	}
	
	public String emitLIMITLOCAL(int in) {
		return ".limit locals "+in+END;
	}
	public String emitVAR(int in,String varName, String inType, int fromLabel, int toLabel) {
		return ".var "+in +" is "+varName+" "+inType+" from Label"+fromLabel+" to Label"+toLabel+END;
	}
	public String emitMETHOD(String lexeme, String type, boolean isStatic) {
		if (isStatic)
			return END + ".method public static "+lexeme+type+END;
		else
			return END + ".method public "+lexeme+type+END;
	}
	public String emitENDMETHOD() {
		return ".end method"+END;
	}

	public String emitSOURCE(String lexeme) throws 	CompilationException {
		return ".source "+lexeme+END;
	}
	
	public String emitCLASS(String lexeme) throws 	CompilationException {
		return ".class "+lexeme+END;
	}
	
	public String emitSUPER(String lexeme) throws 	CompilationException {
		return ".super "+lexeme+END;
	}
	public String emitSTATICFIELD(String lexeme, String type, boolean isFinal ) {
		if (isFinal)
			return ".field static final "+lexeme+" "+type+END;
		else
			return ".field static "+lexeme+" "+type+END;			
	}

	
	public String emitINSTANCEFIELD(String lexeme, String type ) {
		return ".field "+lexeme+" "+type+END;
	}
	
}